Appearance
几个角度规范项目开发
- eslint 对js、ts以及在vue项目中的js代码进行质量和风格的检查。
- stylelint 对css代码,包括sass,less等代码的风格和质量进行检查。
- prettier 专注于对代码风格的修复,可以结果上面两个插件对代码进行自动修复。
- editorconfig用于编辑器的默认行为,比如新建一个文件、新起一行、一个tab键的默认格式等。
- .gitconfig 用于配置当前项目git的默认行为,比如下载的代码是lf还是crlf(mac和windows同学最对碰到的问题),如果使用个人电脑,需要不同的项目对应不同user.name 等需要配置。.git/config文件。
- cz工具能够对commit信息进行编辑。
- husky通过对git add、commit和publish过程的介入,对项目本地化规范。
eslint
eslint通过在项目根目录配置eslintrc.*文件。通过parse选项对文件进行分析。eslint 会从当前文件依次向上检查配置文件,直到文件系统根目录或则碰到一个root: true 的配置文件,利用这个可以给mono配置不同的配置检查,配置文件主要包含一下内容
- env 和 globals 针对全局变量中的检查,比如window变量,document变量等,nodejs的__dirname等等。env 相当于globals的合集。
- parse 和 parseOptions 解析器和解析器选项。 默认是esprima,可以配置成@babel/eslint-parser的 ,支持ts @typescript-eslint/parser 和 支持vue的eslint-plugin-vue。
- rule 配置不同归的规则,key、value形式的对象。value 0 1 2 表示禁用,警告和错误。支持数组的形式调用。数组第二项是rule的参数。
- extends,返回一个有config属性的对象。config属性对应的是配置文件,见后文如何提供一个eslint-plugin。extends都是由插件导入。
- plugins 提供rules的解析,和extends的区别是plugin 提供的是rule规则,但是还未配置。所以一般使用plugin后需要配置相应的extend。plugin 还提供了processor 能力。
- processor 是由plugin 提供,能对非js文件中的js片段提取进行eslint检查。一般都是对应Plugin的extend配置提供。
- overrides 可以覆盖默认的配置,会和全局的定义的配置进行合并
eslint-plugin-vue https://eslint.vuejs.org/rules/
下面配置vue3 eslint为例
npm i -D eslint-plugin-vue
js
module.exports = {
env: {
node: true,
browser: true
},
globals: [
'__webpack_public__path__', // 忽略代码中webpack相关变量
]
parse: 'vue-eslint-parse', // 解析vue中template
parseOptions: {
parse: '@typescript-eslint/parse',
sourceType: 'module'
// ... 其余@typescript-eslint/parse parseOptions
},
plugins: [
'vue' // eslint会默认添加eslint-plugin-vue
'@juqery/test', // @juqery/eslint-plugin-test
'@test' // @test/eslint-plugin @开头总是会处理成组织名
],
extends: [
'plugin:vue' // 去eslint-plugin-vue 包中导入config对象
'test', // eslint-config-test包中导入 // 默认前缀是eslint-config
]
}plugin浅解析
js
// 包 eslint-plugin-xunserver
module.exports = {
rules: {
'xxxx': () => { // rule 定义
create() {
},
meta() {
}
}
}
config: {
vue3: { // 使用时先在plugin中添加rule定义 plugins: ['xunserver'], 然后extends: ['eslint-plugin-xunserver/vue3 或者eslint-plugin-xunserver/vue2']
env: {
node: true,
browser: true,
},
extends: [
'other config'
]
},
vue2: {
// 大致同上
}
},
processor: {
// processor 对象
'xxx': {
}
}
}stylelint
stylelint 配置上同eslint类似。从当前文件开始依次向上寻找.stylelintrc.js配置文件,直到找到为止。同eslint区别是默认都是root配置。大致配置如下
- customSynax,定义解析器,比如在vue和html中使用就需要配置,一般和override搭配使用
- extends, 继承其他配置,可以实现插件和customSynax的引入,和eslint有区别,extends大部分时候还用来配置插件。配置在后面的覆盖前面的,extends引入的会被覆盖。
- plugins,通过插件提供新的规则,一般插件只提供了规则,但是未配置,需要extends配置或者自行配置。
- overrides 能针对不能的文件类型使用不同的配置规则。比如stylelint-config-html/vue 实现了vue的特殊处理。
- rules 对不同的规则配置,null表示规则不生效,其余需要参考rule的实现,数组形式如果第二项是对象,则认为是第二参数。通用的参数有disableFix,message两个关注的。一个可以不处理fix,一个可以自定义报错信息。
- ignoreFiles 忽略文件。第三库不使用stylelint
recss
Reasonable System css, 通过style-config-recss 实现规范
less sass 和 stylus 的解析
使用别人配置好的stylelint-config-standard、stylelint-config-standard-xx 实现,其中stylelint-config-standard是在 stylelint-config-recommend 基础上实现。
如果是自行配置需要,overrides 对应的less、scss和stylus文件,解析器是postcss-less postcss-scss 和 postcss-styl
vue需要安装postcss-html 和对应的postcss-less postcss-scss 等
解决prettier冲突
同理stylelint不解决格式上的问题,需要关闭和prettier冲突的rules。
实现一个extend
js
modules.exports = {
extends: ['others extends'],
overrides: [
{
file: ['*.vue', '**/*.vue'],
customSynax: 'postcss-html'
}
]
}prettier
prettier 是一个format工具,eslint和stylelint同时具有lint和format功能,执行顺序是eslint => prettier 或者stylelint => prettier。 prettier 的配置文件比较简单,一共就10多个选项,使用时指定需要使用的文件即可,prettier在项目中使用意义不大,主要是不能在codeActionSave中使用。目前prettier对css 和 js的格式化都交给对应的格式化工具,不够prettier 对其他语法的格式化还是比较好用,还是建议在编辑保留。 prettier还会使用editorconfig中的配置来初始化配置,如果新建文件总是报错飘红,建议检查editorconfig 和 prettier中冲突的部分。
vscode中引入格式化工具
vscode 区分为工作区和用户区配置(本地和全局),vscode提供了两种format方式,一种是codeActionOnSave,表示保存时调用格式化工具。另一个是defaultEditor: 'xxx', 表示使用快捷键格式化时调用的工具。
- codeActionOnSave和formatOnSave, formateOnSave是defaultEditor在保存时调用的方式,现在基本启用。codeActionOnSave支持多个格式化程序依次调用。vscode插件在初始化时会向vscode注册format功能
vscode针对不同类型的文件能够采用不同的配置,"[html]"为html类型的文件采用特定的配置。
vue中template如何格式化
vue中template中规范prop能够保证良好的编码思路。建议加上vue/attributes-order。
husky、lint-stage、commitizen和cz-customizable
- husky 用于在git的各种阶段执行脚本,如果脚本返回错误,停止流程。
- list-stage 用于只校验暂存区文件,提高lint速度,在校验文件时,会从文件的当前的目录开始查找最近的配置,在根目录配置baseconfig,子目录继承。
- commitizen是一个检查commit message的工具。支持各种adapter。cz-customizable 是对应的adapter。安装好后使用git-cz代替git commit。该方案不能很好的和vscode结合,不采用。
- commitlint 检查commit msg是否合规,结合husky实现commit信息的校验。
husky安装配置
pnpm add husky -Dw // 项目安装在根目录 pnpm set-script prepare "husky install" 配置package.json script.prepare 脚本 pnpm husky install // 初始化husky pnpm add './husky/pre-commit' 'lint-stage' // 不同包调用自身的lint-stage 方法 pnpm add './husky/pre-push' 'pnpm -F "./packages/**" run lint' // 全局校验
list-stage
在子项目中单独配置.lintstagedrc.js文件,文件内容如下。
js
// .lintstagedrc.js
const baseConfig = require('../../.lintstagedrc.js')
module.exports = {
...baseConfig,
'*.{js,jsx,ts,tsx.vue,html}': ['eslint --config .eslintrc.js'],
'*.{css,scss,sass,less,styl,vue,html}': ['stylelint --config .stylelintrc.js']
'*.{ts,tsx,js,jsx,json,html,yml,css,less,scss,md,sass}': ['prettier --write']
}commitlint
pnpm add commitlint -Dw pnpm husky add './hasky/commit-msg' 'pnpm commitlint --config .commitlintrc.js --edit $1' 添加.commitlintrc.js文件
js
/**
* build : 改变了build工具 如 webpack
* ci : 持续集成新增
* chore : 构建过程或辅助工具的变动
* feat : 新功能
* docs : 文档改变
* fix : 修复bug
* perf : 性能优化
* refactor : 某个已有功能重构
* revert : 撤销上一次的 commit
* style : 代码格式改变
* test : 增加测试
* anno: 增加注释
*/
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [
2,
'always',
[
'build',
'ci',
'chore',
'docs',
'feat',
'fix',
'perf',
'refactor',
'revert',
'style',
'test',
'anno',
],
],
},
};eslintrc.js和eslintignore 文件
eslint(stylelint)在执行时,按照如下执行。
- 确定当前使用的eslint文件位置,确定执行的上下文。
- 确定需要处理的全部文件
- 根据上下文中中的.eslitingnore、命令中的--no-ignore、--ext 确定需要处理的最终文件合集
- 一个一个文件的查找eslintrc配置,找到配置后执行eslint。配置的查找规则从当前需要检查的配置往上级目录查找,知道文件系统的根目录或者碰到一个root:true的配置文件,这种方式相当于变相实现了继承(stylelint在查找到第一个配置文件后停止,意味着需要自行实现继承)。
vscode中eslint和stylelint
vscode执行逻辑大致同上,只是确定文件的方式有所不同。
- vscode打开时加载项目根目录下的ignore文件
- 根据vscode中的no-ignore 和插件配置的生效文件确定最终文件。
lint-staged 如何实现只检查部分文件
eslint,styllint和prettier均支持stdin方式确定输入文件。lint-staged把需要检查的文件和配置一一对比,确定出需要执行命令的文件,添加在命令后。 lintstagedrc的查找方式从被检查的文件开始向上查找,lintstagedrc中指令执行的上下和本身相同
js
// lintstagedrc.js
module.exports = {
"*.(vue,ts,tsx,js,jsx)": "eslint" // 相当于执行在.lintstagedrc.js所在目录下执行eslint xx.js命令
}monorepo格式化解决方案
monorepo仓库有如下难点需要解决。
- 不同项目使用不同技术栈,采用的规范不一致。
- CI和lint-staged中的校验是全局的。
- vscode编辑器总是从项目根目录读取工具并加载ignore文件。 针对以上问题,解决方案如下
- 不同的子项目在编码时,建议到对应的子目录下编写,目的是为了匹配vscode的格式化功能。
- 不同子项目在配置时,通通引用公共的配置
- ci和git 校验时采用调用各子项目中的lint工具。
